package pe.gob.foncodes.ssa.bs.administracion.controller;

import java.util.List;
import javax.faces.event.ActionEvent;
import org.apache.commons.beanutils.BeanUtils;
import pe.gob.foncodes.ssa.bs.common.controller.GenericController;
import pe.gob.foncodes.ssa.bs.common.util.ExpressionsValidator;

public class GenericMaintenanceController extends GenericController {

    /** Sirve para buscar el atributo principal del bean para realizar validaciones 
     * que indiquen si que este campo tiene un formato vlido y es nico o se encuentra repetido.
     * <i>Por ejemplo: setMainAttribute("codigo") >>> se realizarn validaciones al campo "codigo" 
     * del bean en el mtodo {@link #validateCodigo()} </i>*/
    private String mainAttribute;
    private String nombre;

    @Override
    public boolean validate() throws Exception {
        if (!super.validate()) {
            return false;
        }
        if (!validateCodigo()) {
            return false;
        }

        return true;
    }

    public void quitaEspaciosAlGrabar() throws Exception {
        String nombre = BeanUtils.getProperty(getBean(), "nombre");
        BeanUtils.setProperty(getBean(), "nombre", nombre.trim());
    }

    @Override
    public void init() throws Exception {
        setBean(getBeanInstance());
        setBeanList(getService().findByObject(getBeanInstance()));
    }

    @Override
    public void afterSave(ActionEvent event) throws Exception {
        setMessageSuccess("La transaccin ha sido ejecutada satisfactoriamente.");
        super.refreshBeanList();
    }

    @Override
    public void afterDelete(ActionEvent event) throws Exception {
        init();
        super.refreshBeanList();
    }

    /**
     * Valida que el cdigo del bean tenga slo valores alfanumricos. Adems, valida 
     * que no se registren cdigos duplicados ya sea por insercin o actualizacin de
     * datos.
     * @return <b>true</b> en caso que cumpla con las validaciones descritas y <b>false</b> 
     * en caso contrario.
     * @throws Exception
     */
    public boolean validateCodigo() throws Exception {
        String idTmp = null;
        String codigo = null;
        Long id = null;
        if (mainAttribute == null || mainAttribute.equals("")) {
            setMainAttribute("codigo");
        }
        try {
            codigo = BeanUtils.getProperty(getBean(), mainAttribute);
            codigo = codigo.trim();
            if (codigo.equals("")) {
                return false;
            }
            if (!ExpressionsValidator.validarSoloAlfanumerico(codigo)) {
                setMessageError("El " + mainAttribute + " slo puede tener caracteres alfanumricos, y los smbolos guin (-) y guin abajo (_).");
                return false;
            }
            idTmp = BeanUtils.getProperty(getBean(), "id");
            if (idTmp != null && !idTmp.equals("")) {
                id = new Long(idTmp);
            }
        } catch (Exception e) {
            log.info("Ocurri un error al validar id y " + mainAttribute + " de " + getBean().getClass().getName());
            return false;
        }
        //se realiza la busqueda del atributo de tres formas para econtrar algun repedido
        //en la base de datos 15/04/2010 E. Pomayay.
        Object obj = getBeanInstance();
        BeanUtils.setProperty(obj, mainAttribute, codigo.toLowerCase());
        Object obj2 = getBeanInstance();
        BeanUtils.setProperty(obj2, mainAttribute, codigo.toUpperCase());
        Object obj3 = getBeanInstance();
        BeanUtils.setProperty(obj3, mainAttribute, codigo);
        if (id == null) {
            List<Object> lstTmp = getService().findByObject(obj);
            List<Object> lstTmp2 = getService().findByObject(obj2);
            List<Object> lstTmp3 = getService().findByObject(obj3);
            if (!lstTmp.isEmpty() || !lstTmp2.isEmpty() || !lstTmp3.isEmpty()) {
                setMessageError("El " + mainAttribute + " ingresado ya existe. Debe ingresar uno distinto.");
                return false;
            }
        } else {
            obj = getBeanInstance();
            obj = getService().findById(getBean().getClass(), id);
            String codigoTmp = BeanUtils.getProperty(obj, mainAttribute);
            if (!codigoTmp.equals(codigo)) {
                obj = getBeanInstance();
                BeanUtils.setProperty(obj, mainAttribute, codigo.toLowerCase());
                obj2 = getBeanInstance();
                BeanUtils.setProperty(obj2, mainAttribute, codigo.toUpperCase());
                obj3 = getBeanInstance();
                BeanUtils.setProperty(obj3, mainAttribute, codigo);
                List<Object> lstTmp = getService().findByObject(obj);
                List<Object> lstTmp2 = getService().findByObject(obj2);
                List<Object> lstTmp3 = getService().findByObject(obj3);
                if (!lstTmp.isEmpty() || !lstTmp2.isEmpty() || !lstTmp3.isEmpty()) {
                    setMessageError("El " + mainAttribute + " que se trata de actualizar ya existe. Debe ingresar uno distinto.");
                    return false;
                }
            }
        }
        BeanUtils.setProperty(getBean(), mainAttribute, codigo);
        return true;
    }

    public void listarLog(ActionEvent event) throws Exception {
        List<Object> lista = getService().findByNamedQuery(getBeanBusqueda().getClass().getSimpleName() + ".findLog", new Object[]{Long.valueOf(getRequestParameter("paramLog"))});
        setBeanListLog(lista);
    }

    public void listarLogCausal(ActionEvent event) throws Exception {
        List<Object> lista = getService().findByNamedQuery(getBeanBusqueda().getClass().getSimpleName() + ".findLogbyId", new Object[]{Long.valueOf(getRequestParameter("paramLog")), Long.valueOf(getRequestParameter("paramVer"))});
        setBeanBusqueda(lista.get(0));
    }

    public String getMainAttribute() {
        return mainAttribute;
    }

    public void setMainAttribute(String mainAttribute) {
        this.mainAttribute = mainAttribute;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
}
